package thread;

import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA
 * Description：模拟实现Timer
 * User：chenshu
 * Date：2023-11-09
 * Time：20:24
 */

abstract class MyTimerTask implements Runnable {
    @Override
    public void run(){}
}
class MyTask implements Comparable<MyTask>{
    private MyTimerTask command;
    long startTime;
    public MyTask(MyTimerTask command, long after) {
        this.command = command;
        startTime = System.currentTimeMillis() + after;
    }

    public void run() {
        command.run();
    }

    public long getStartTime() {
        return startTime;
    }

    @Override
    public int compareTo(MyTask o) {
        return (int) (this.startTime - o.startTime);
    }
}
class MyTimer {
    Object locker = new Object();
    //定义一个优先级队列来存放任务
    PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    public void schedule(MyTimerTask command, long after) {
        synchronized (locker) {
            MyTask myTask = new MyTask(command, after);
            queue.put(myTask);
            //插入新任务，就唤醒并重新计算wait时间
            locker.notify();
        }
    }

    public MyTimer() {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()){
                try {
                    synchronized (locker) {
                        //没有就阻塞，有就拿出
                        //下面这段代码为了预防死锁
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        MyTask curTask = queue.take();
                        //检查时间是否到，到了就运行，没到就放回
                        if (System.currentTimeMillis() < curTask.startTime) {
                            //没到放回
                            queue.put(curTask);
                            locker.wait(curTask.getStartTime() - System.currentTimeMillis());
                        } else {
                            //到了执行
                            curTask.run();
                        }
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t.start();
    }
}
public class Demo1 {
    public static void main(String[] args) {
        MyTimer myTimer= new MyTimer();
        myTimer.schedule(new MyTimerTask(){
            @Override
            public void run() {
                System.out.println("3333");
            }
        }, 6000);
        myTimer.schedule(new MyTimerTask(){
            @Override
            public void run() {
                System.out.println("2222");
            }
        }, 4000);
        myTimer.schedule(new MyTimerTask(){
            @Override
            public void run() {
                System.out.println("1111");
            }
        }, 2000);

        System.out.println("hello world");
    }
}
